/*
 * *****************************************************************************
 *  Copyright ( c ) 2019 huibur Inc. All Rights Reserved.
 *
 *  This software is the confidential and proprietary information of Huibur Inc
 *  (*Confidential Information*). You shall not disclose such Confidential Information
 *  and shall use it only in accordance with the terms of the license agreement
 *  you entered into with Huibur or a Huibur authorized
 *  reseller (the "License Agreement*).
 *  ******************************************************************************
 */

package com.huibur.devicecheck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huibur.devicecheck.enums.DeviceEnums;
import com.huibur.devicecheck.exception.CheckLocationNameRepeatException;
import com.huibur.devicecheck.mapper.CheckLocationMapper;
import com.huibur.devicecheck.mapper.DeviceMapper;
import com.huibur.devicecheck.model.param.CheckLocationParam;
import com.huibur.devicecheck.model.po.CheckLocationPO;
import com.huibur.devicecheck.model.po.DevicePO;
import com.huibur.devicecheck.model.query.CheckLocationQuery;
import com.huibur.devicecheck.model.vo.*;
import com.huibur.devicecheck.request.ObjRes;
import com.huibur.devicecheck.request.PageRes;
import com.huibur.devicecheck.request.SessionContext;
import com.huibur.devicecheck.service.ICheckLocationService;
import com.huibur.devicecheck.utils.ConvertPageUtil;
import com.huibur.devicecheck.utils.DateUtils;
import org.apache.commons.codec.binary.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CheckLocationServiceImpl extends ServiceImpl<CheckLocationMapper, CheckLocationPO> implements ICheckLocationService {

    @Autowired
    CheckLocationMapper checkLocationMapper;
    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 新增位置
     *
     * @param checkLocationParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> insert(CheckLocationParam checkLocationParam) {
        CheckLocationPO checkLocation = checkLocationMapper.selectOne(new LambdaQueryWrapper<CheckLocationPO>()
                .eq(CheckLocationPO::getParentId, checkLocationParam.getParentId())
                .eq(CheckLocationPO::getName, checkLocationParam.getName())
                .eq(CheckLocationPO::getIsDeleted, 0)
                .eq(CheckLocationPO::getStatus, 0));
        if (null != checkLocation) {
            throw new CheckLocationNameRepeatException();
        }

        CheckLocationPO checkLocationPO = new CheckLocationPO();
        checkLocationPO.setParentId(checkLocationParam.getParentId());
        checkLocationPO.setName(checkLocationParam.getName());
        checkLocationPO.setSeq(checkLocationParam.getSeq());
        checkLocationPO.setIsDeleted(0);
        checkLocationPO.setCreateAt(DateUtils.getCurrentTimestamp());
        checkLocationPO.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
        checkLocationPO.setStatus(0);
        checkLocationPO.setIsSubset(false);
        checkLocationMapper.insert(checkLocationPO);

        //修改上级的子集状态和路由的拼接
        if (checkLocationParam.getParentId() != 0) {
            Long parentId = checkLocationPO.getParentId();
            CheckLocationPO selectOne = checkLocationMapper.selectOne(new LambdaQueryWrapper<CheckLocationPO>()
                    .eq(CheckLocationPO::getId, parentId)
                    .eq(CheckLocationPO::getIsDeleted, 0));
            selectOne.setIsSubset(true);
            checkLocationPO.setDescription(selectOne.getDescription() + "/" + checkLocationPO.getName());
            checkLocationPO.setRoute(selectOne.getRoute() + checkLocationPO.getId() + "|");
            checkLocationMapper.updateById(selectOne);
        } else {
            checkLocationPO.setDescription(checkLocationPO.getName());
            checkLocationPO.setRoute("|" + checkLocationPO.getId().toString() + "|");
        }
        checkLocationMapper.updateById(checkLocationPO);
        return new ObjRes<Void>().success("创建成功");
    }

    /**
     * 删除地址
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        CheckLocationPO checkLocationPO = new CheckLocationPO();

        checkLocationPO.setIsDeleted(1);
        //        checkLocationPO.setId(id);
        //        checkLocationMapper.updateById(checkLocationPO);

        List<Long> longs = new ArrayList<>();
        longs.add(id);
        getIdByParentId(longs, longs);


        checkLocationMapper.update(checkLocationPO, new LambdaQueryWrapper<CheckLocationPO>()
                .in(CheckLocationPO::getId, longs));
        return true;
    }

    public void getIdByParentId(List<Long> parentIdList, List<Long> list) {
        if (!CollectionUtils.isEmpty(parentIdList)) {
            List<CheckLocationPO> checkLocationPOS = this.baseMapper.selectList(new LambdaQueryWrapper<CheckLocationPO>()
                    .in(CheckLocationPO::getParentId, parentIdList));
            List<Long> idList = checkLocationPOS.stream().map(item -> item.getId()).collect(Collectors.toList());
            list.addAll(idList);
            getIdByParentId(idList, list);
        }
    }


    /**
     * 编辑地址
     *
     * @param id
     * @param checkLocationParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> updateLocation(Long id, CheckLocationParam checkLocationParam) {
        CheckLocationPO checkLocation = checkLocationMapper.selectOne(new LambdaQueryWrapper<CheckLocationPO>()
                .ne(CheckLocationPO::getId, id)
                .eq(CheckLocationPO::getParentId, checkLocationParam.getParentId())
                .eq(CheckLocationPO::getName, checkLocationParam.getName())
                .eq(CheckLocationPO::getIsDeleted, 0)
                .eq(CheckLocationPO::getStatus, 0));
        if (null != checkLocation) {
            throw new CheckLocationNameRepeatException();
        }

        CheckLocationPO oldData = checkLocationMapper.selectById(id);

        List<CheckLocationPO> checkLocationPOS = checkLocationMapper.selectList(Wrappers.<CheckLocationPO>lambdaQuery().likeRight(CheckLocationPO::getRoute, checkLocationParam.getRoute()));
        CheckLocationPO locationPO = checkLocationPOS.get(0);
        int index = 0;
        String[] split = locationPO.getRoute().split("\\|");
        List<String> collect = Arrays.asList(split).stream().filter(item -> !item.equals("")).collect(Collectors.toList());
        for (int i = 0; i < collect.size(); i++) {
            if (collect.get(i).equals(id + "") ) {
                index = i;
            }
        }
        CheckLocationPO checkLocationPO = new CheckLocationPO();
        for (CheckLocationPO po : checkLocationPOS) {

            String description = po.getDescription();
            String[] split1 = description.split("\\/");
            split1[index] = checkLocationParam.getName();
            String str = String.join("/", split1);
            po.setDescription(str);
            if (po.getId().equals(id)){
                checkLocationPO.setDescription(str);
            }
        }

        this.updateBatchById(checkLocationPOS);


        checkLocationPO.setParentId(checkLocationParam.getParentId());
        checkLocationPO.setName(checkLocationParam.getName());
        checkLocationPO.setSeq(checkLocationParam.getSeq());
        checkLocationPO.setIsDeleted(0);
        checkLocationPO.setUpdateAt(DateUtils.getCurrentTimestamp());
        checkLocationPO.setUpdateBy(SessionContext.getCurrentUserSubject().getUserId());
        checkLocationPO.setStatus(0);
        checkLocationMapper.update(checkLocationPO, new LambdaQueryWrapper<CheckLocationPO>()
                .eq(CheckLocationPO::getId, id));



        return new ObjRes<Void>().success("修改成功");
    }

    /**
     * 地址列表(查询并分页)
     *
     * @param checkLocationQuery
     * @return
     */
    @Override
    public PageRes<CheckLocationVO> selectLocationList(CheckLocationQuery checkLocationQuery) {
        Page<CheckLocationPO> page = new Page<>(checkLocationQuery.getCurrent(), checkLocationQuery.getPageSize());
        IPage<CheckLocationVO> pages = checkLocationMapper.selectLocationList(page, checkLocationQuery);
        return ConvertPageUtil.convertPage(checkLocationQuery.getCurrent(), page.getTotal(), pages.getRecords());
    }

    /**
     * 根据ID来查询子级
     *
     * @param id
     * @return
     */
    @Override
    public List<CheckLocationPO> selectByParentId(Long id) {
        List<CheckLocationPO> checkLocationPOList = checkLocationMapper.selectByParentId(id);
        checkLocationPOList.sort((x, y) -> Integer.compare(x.getSeq(), y.getSeq()));
        return checkLocationPOList;
    }

    /**
     * 查询所有的节点
     *
     * @param id
     * @return
     */
    @Override
    public List<LocationVO> selectAllLocation(Long id) {
        List<LocationVO> locationVOList = checkLocationMapper.selectAllLocation(id);
        return locationVOList;
    }

    /**
     * 后台管理端首页统计图（地点统计）
     *
     * @param locationId
     * @return
     */
    @Override
    public List<LocationStaVO> locationStatistics(Long locationId) throws ParseException {
        Calendar cal = Calendar.getInstance();
        //获取年份
        int year = cal.get(Calendar.YEAR);
        //获取月份
        int month = cal.get(Calendar.MONTH) + 1;
        //获取当前月最第一天
        String firstDayOfMonth = TaskRecordServiceImpl.getFirstDayOfMonth(month);
        //获取当前月最后一天
        String lastDayOfMonth = TaskRecordServiceImpl.getLastDayOfMonth(month);

        String format = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Timestamp firstTimestamp = new Timestamp(sdf.parse(firstDayOfMonth).getTime());
        Timestamp lastTimestamp = new Timestamp(sdf.parse(lastDayOfMonth).getTime());

        locationId = locationId == null ? 0 : locationId;

        List<CheckLocationPO> checkLocationPOList = checkLocationMapper.selectList(new LambdaQueryWrapper<CheckLocationPO>()
                .eq(CheckLocationPO::getParentId, locationId)
                .eq(CheckLocationPO::getIsDeleted, 0)
                .eq(CheckLocationPO::getStatus, 0));

        ArrayList<LocationStaVO> voArrayList = new ArrayList<>();

        for (CheckLocationPO checkLocationPO : checkLocationPOList) {
            LocationStaVO locationStaVO = new LocationStaVO();
            locationStaVO.setLocationId(checkLocationPO.getId());
            locationStaVO.setLocationName(checkLocationPO.getName());

            //统计图中直接将两组数据查出来
            List<StatisticVO> statisticVOList = this.baseMapper.selectStatusNum(checkLocationPO.getId(), firstTimestamp, lastTimestamp);

            RecordStatusVO recordStatusVO = new RecordStatusVO();
            for (StatisticVO statisticVO : statisticVOList) {
                //状态为0 则为  正常状态的个数
                if (statisticVO.getStatus().equals(0)) {
                    recordStatusVO.setNormalCount(statisticVO.getNum());
                }
                //状态为1 则为  异常状态的个数
                if (statisticVO.getStatus().equals(1)) {
                    recordStatusVO.setAbnormalCount(statisticVO.getNum());
                }
            }

            String locationId1 = "|" + checkLocationPO.getId() + "|";
            Integer integer = this.baseMapper.findTotalByLocation(locationId1);

            recordStatusVO.setNormalCount(recordStatusVO.getNormalCount() == null ? 0 : recordStatusVO.getNormalCount());
            recordStatusVO.setAbnormalCount(recordStatusVO.getAbnormalCount() == null ? 0 : recordStatusVO.getAbnormalCount());
            recordStatusVO.setNotCheckCount(integer - recordStatusVO.getNormalCount() - recordStatusVO.getAbnormalCount());
            locationStaVO.setRecordStatusVO(recordStatusVO);

            voArrayList.add(locationStaVO);
        }
        return voArrayList;
    }
}
